home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-19 | 5.8 KB | 235 lines | [TEXT/CWIE] |
- /*
- File: Int64.c
-
- Contains: 64-bit math class
-
- Written by: Dave Owens, tweeked by Andy Nicholas and Chris Bingham
-
- Copyright: © 1994-1995 by Apple Computer, Inc., all rights reserved.
-
- <3> 3/20/95 andy
- */
-
- #ifdef MWTRACEBACKTABLES
- #pragma traceback on
- #endif
-
- #include "Int64.h"
-
- #pragma segment LookupSizes
-
- //========================================================================================
- // CLASS Int64
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // Int64::IntuitOtherOperand:
- //
- // IntuitOtherOperand
- //
- // This function decodes the input data and makes sure that it is packaged into
- // an Int64.
- //----------------------------------------------------------------------------------------
- const Int64* Int64::IntuitOtherOperand(SInt16 operation, const void* input, Int64* otherStorage)
- {
- int type = operation & typeMask;
- if (type == typeOtherIsInt64)
- return (const Int64*) input;
-
- otherStorage->fSInt64.hi = 0;
-
- switch (type)
- {
- case typeOtherIsInt:
- {
- if (*(const int*)input < 0)
- otherStorage->fSInt64.hi = -1;
-
- otherStorage->fSInt64.lo = *(const int*) input;
- break;
- }
- case typeOtherIsLong:
- {
- if (*(const SInt32*)input < 0)
- otherStorage->fSInt64.hi = -1;
-
- otherStorage->fSInt64.lo = *(const UInt32*) input;
- break;
- }
-
- default:
- otherStorage->fSInt64.lo = *(const UInt32*) input;
- }
-
- return otherStorage;
- } // Int64::IntuitOtherOperand
-
-
- //----------------------------------------------------------------------------------------
- // Int64::Operation:
- //----------------------------------------------------------------------------------------
- Int64 Int64::Operation(SInt16 operation, const void* input) const
- {
- Int64 sourceStorage;
-
- Int64 main;
- main.fSInt64.hi = fSInt64.hi;
- main.fSInt64.lo = fSInt64.lo;
-
- const Int64* other = IntuitOtherOperand(operation, input, &sourceStorage);
- UInt32 temp;
-
- switch (operation & verbMask)
- {
- case verbAssign:
- {
- main.fSInt64.hi = other->fSInt64.hi;
- main.fSInt64.lo = other->fSInt64.lo;
- }
- break;
-
- case verbAdd:
- {
- temp = main.fSInt64.lo + other->fSInt64.lo;
- if ((temp < main.fSInt64.lo) && (temp < other->fSInt64.lo))
- ++main.fSInt64.hi; // catch overflow
- main.fSInt64.lo = temp;
- main.fSInt64.hi += other->fSInt64.hi;
- }
- break;
-
- case verbSubtract:
- {
- if (other->fSInt64.lo > main.fSInt64.lo) // catch underflow
- --main.fSInt64.hi;
- main.fSInt64.lo -= other->fSInt64.lo;
- main.fSInt64.hi -= other->fSInt64.hi;
- }
- break;
-
- //
- // ••• this code needs to be replaced by something that works,
- // preferably a call to the 64-bit math library!
- //
- case verbMultiply:
- {
- if ((main == Int64(0L) ) || (*other == Int64(0L) ))
- main = 0;
- else
- {
- // assumes a maximum multiply of 48 bits * 31 bits
- UInt16 a3 = (main.fSInt64.hi & 0xFFFF);
- UInt16 a2 = (main.fSInt64.lo & 0xFFFF0000) >> 16;
- UInt16 a1 = (main.fSInt64.lo & 0xFFFF);
- UInt16 b2 = (other->fSInt64.lo & 0xFFFF0000) >> 16;
- UInt16 b1 = (other->fSInt64.lo & 0xFFFF);
-
- main = (UInt32) ((a3 * b2));
- main <<= 16;
- main += (UInt32) ((a3 * b1) + (a2 * b2));
- main <<= 16;
- main += (UInt32) ((a2 * b1) + (a1 * b2));
- main <<= 16;
- main += (UInt32)(a1 * b1);
- }
- }
- break;
-
- //
- // ••• this code needs to be replaced by something that works,
- // preferably a call to the 64-bit math library!
- //
- case verbDivide:
- {
- if ((main == Int64(0L) ) || (*other == Int64(0L) ))
- main = 0;
- else
- {
- // other->fSInt64.lo is the denominator
- SInt32 numerator = main.fSInt64.hi;
- Int64 times;
- times.fSInt64.hi = numerator / other->fSInt64.lo;
-
- numerator -= times.fSInt64.hi * other->fSInt64.lo;
- numerator = (numerator << 16) | (main.fSInt64.lo >> 16);
- times.fSInt64.lo = numerator / other->fSInt64.lo;
-
- numerator -= times.fSInt64.lo * other->fSInt64.lo;
- numerator = (numerator << 16) | (main.fSInt64.lo & 0xFFFF);
- times.fSInt64.lo <<= 16;
- times.fSInt64.lo += numerator / other->fSInt64.lo;
-
- main.fSInt64.hi = times.fSInt64.hi;
- main.fSInt64.lo = times.fSInt64.lo;
- }
- }
- break;
-
- case verbShiftRight:
- {
- // ASSERT(*other < 64);
- temp = other->fSInt64.lo;
- main.fSInt64.lo = (main.fSInt64.hi << (32 - temp)) | (main.fSInt64.lo >> temp);
- main.fSInt64.hi = main.fSInt64.hi >> temp;
- }
- break;
-
- case verbShiftLeft:
- {
- // ASSERT(*other < 64);
- temp = other->fSInt64.lo;
- main.fSInt64.hi = (main.fSInt64.hi << temp) | (main.fSInt64.lo >> (32 - temp));
- main.fSInt64.lo = main.fSInt64.lo << temp;
- }
- break;
-
- default:
- // ASSERT(false);
- break;
- }
-
- return main;
- }
-
- //----------------------------------------------------------------------------------------
- // Int64::Comparison:
- //----------------------------------------------------------------------------------------
- Boolean Int64::Comparison(SInt16 comparison, const void* input) const
- {
- Int64 otherStorage;
-
- const Int64* other = IntuitOtherOperand(comparison, input, &otherStorage);
- Boolean result = false;
- Boolean negateResult = false;
-
- switch (comparison & cmpMask)
- {
- case cmpNotEqual:
- negateResult = true;
- case cmpEqual:
- result = (fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo == other->fSInt64.lo);
- break;
-
- case cmpGreaterOrEqual:
- negateResult = true;
- case cmpLess:
- result = (fSInt64.hi < other->fSInt64.hi) ||
- ((fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo < other->fSInt64.lo));
- break;
-
- case cmpLessOrEqual:
- negateResult = true;
- case cmpGreater:
- result = (fSInt64.hi > other->fSInt64.hi) ||
- ((fSInt64.hi == other->fSInt64.hi) && (fSInt64.lo > other->fSInt64.lo));
- break;
-
- default:
- // ASSERT(false);
- break;
- }
-
- return result ^ negateResult;
- } // Int64::Comparison
-
-